package practicados;

import java.util.ResourceBundle;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 *
 * @author Ricardo Yepes
 */
public final class PersonDAO {

    /** The only object who can do database operations. */
    private static PersonDAO singleton;

    /** Resource bundle to get constants. */
    private static ResourceBundle databaseBundle;

    /** User to connect to the database. */
    private static String user;

    /** Password to connect to the database. */
    private static String pass;

    /** Connection string to the database. */
    private static String url;

    /** Driver to connect to the database. */
    private static String driver;

    /** Represents the database connection. */
    private static Connection connection;

    /**
     * Constructor to force the singleton usage.
     */
    private PersonDAO() {
    }

    /**
     * Obtains the only instance of the class.
     * @return the only instance of the class
     */
    public static PersonDAO getInstance() {
        if (singleton == null) {
            singleton = new PersonDAO();
            databaseBundle = ResourceBundle.getBundle("conf.database");
            user = databaseBundle.getString("userDB");
            pass = databaseBundle.getString("passDB");
            url = databaseBundle.getString("urlDB");
            driver = databaseBundle.getString("driverDB");
            try {
                Class.forName(driver);
                connection = DriverManager.getConnection(url, user, pass);
            } catch (SQLException ex) {
                System.out.println("No pudo establecese la conexión.");
                System.exit(-1);
            } catch (ClassNotFoundException ex) {
                System.out.println("Driver incorrecto.");
                System.exit(-1);
            }
        }
        return singleton;
    }

    /**
     * Query a Person frome de database.
     * @param identification The identification of the person
     * @return the Person who identification was provided
     * @throws SQLException if the select query fails
     */
    public Person read(final Integer identification) throws SQLException {
        PreparedStatement read = connection.prepareStatement(
                databaseBundle.getString("sqlSelectPersonaByCedula"));
        try {
            read.setInt(1, identification);
            ResultSet rs = read.executeQuery();
            try {
                rs.next();
                Person person = new Person(
                        identification,
                        rs.getString("nombre"),
                        rs.getString("apellido"),
                        rs.getInt("edad"));

                return person;
            } finally {
                rs.close();
            }
        } finally {
            read.close();
        }
    }

    /**
     * Save a Person on the database.
     * @param person Person to be saved
     * @throws SQLException if the insert fails
     */
    public void save(final Person person) throws SQLException {
        PreparedStatement save = connection.prepareStatement(
                databaseBundle.getString("sqlInsertPersona"));

        java.sql.Date fecha = null;
        if (person.getBirthDate() != null) {
            fecha = new java.sql.Date(person.getBirthDate().getTime());
        }

        Integer index = 0;
        save.setInt(++index, person.getIdentity());
        save.setString(++index, person.getName());
        save.setString(++index, person.getLastName());
        save.setInt(++index, person.getAge());
        save.setDate(++index, fecha);
        save.execute();

    }

    /**
     * Update a Person on the database.
     * @param person Person to be saved
     * @throws SQLException if the insert fails
     */
    public void update(final Person person) throws SQLException {
        PreparedStatement update = connection.prepareStatement(
                databaseBundle.getString("sqlUpdatePersona"));
        Integer index = 0;
        try {
            update.setString(++index, person.getName());
            update.setString(++index, person.getLastName());
            update.setInt(++index, person.getAge());
            java.sql.Date date = null;
            if (person.getBirthDate() != null) {
                date = new java.sql.Date(person.getBirthDate().getTime());
            }
            update.setDate(++index, date);
            update.setInt(++index, person.getIdentity());
            update.execute();
        } finally {
            update.close();
        }
    }

    /**
     * Delete a Person frome de database.
     * @param person The person who will be deleted
     * @throws SQLException if the select query fails
     */
    public void delete(final Person person) throws SQLException {
        PreparedStatement delete = connection.prepareStatement(
                databaseBundle.getString("sqlDeletePersona"));
        try {
            delete.setInt(1, person.getIdentity());
            delete.execute();
        } finally {
            delete.close();
        }
    }

}
